/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.splayer.mediaplayer;

import android.R.integer;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.Toast;

import com.splayer.mediacodec.AndroidMediaCodec;
import com.splayer.mediacodec.PlayerHelper;


public class Player extends Activity implements SurfaceHolder.Callback, OnTouchListener,OnGestureListener
{
	private static final String TAG = "com.splayer.mediaplayer";
	private static final String SAMPLE = "http://m.flvcd.com/player.php?url=http://v.youku.com/v_show/id_XNzU3NzY5NjIw.html&format=super";// fenghuangshipin
//	private static final String SAMPLE = "http://cctv2.vtime.cntv.cloudcdn.net:8000/live/no/204_/seg0/index.m3u8?AUTH=2eSRGfMomAZDNyEn0WnnuwsBkE44WRYC4V6C6+Ika32dFClnMvyxNZdyM45/24QwlSKY4Ukzc9CJG93zUx+o8A=="; //guangdongweishi
//	private static final String SAMPLE ="http://zb.v.qq.com:1863/?progid=3900155972";
//	private static final String SAMPLE = "http://122.227.245.147:8000/live/flv/channel64";
//	private static final String SAMPLE = "http://124.160.184.142:80/live/5/30/e9301e073cf94732a380b765c8b9573d.m3u8?type=m3u8.web.pad";//hunan
//	private static final String SAMPLE = "http://123.125.89.25/m3u8/cctv1HD_1300/desc.m3u8?stream_id=cctv1HD_1300&ltm=1412077735&lkey=85559275add7170e4b901e228853b4f2&platid=10&splatid=1014&tag=live&video_type=m3u8&useloc=0&mslice=5&path=123.125.89.19,111.206.215.6,123.125.91.37&buss=0&qos=3&cips=10.58.54.231&geo=CN-1-9-2&tmn=1412059735&pnl=706,769,260&rson=1&ext=m3u8&sign=live_tv&termid=3&playid=1&play=0&ostype=android&hwtype=C1S&lstm=1XYrDN&lsbv=v&lssv=1py5rs&lsdg=KJfnWB6OhXaJJGRE816GEC&m3v=1&utp=683&utpid=60814c85339435aaa4c987ef11094383&appid=10&rnd=7533661";
	/*
	 * After player prepare done,you can start the player.
	 */
	private static final int PLAYER_EVENT_PREPAREDONE = 0;
	/*
	 * Report the video size,you can use this to set the surface width and height
	 */
	private static final int PLAYER_EVENT_VIDEO_SIZE = 1;
	/*
	 * The seek is completely,you can update the seek bar
	 */
	private static final int PLAYER_EVENT_SEEK_COMPLETELY = 2;
	/*
	 * The stream is play end
	 */
	private static final int PLAYER_EVENT_EOS = 3;
	/*
	 * There is no enough data for play, the player will pause auto,downloading the data...
	 */
	private static final int PLAYER_EVENT_REBUFFER_START = 4;
	/*
	 * The data is enough to be play ,The player will play if the player
	 *  is paused by no enough data
	 */
	private static final int PLAYER_EVENT_REBUFFER_END = 5;
	/*
	 * Can't find any media stream in the recourse,this is a error message
	 */
	private static final int PLAYER_EVENT_ERROR_NO_STREAM = 6;
	/*
	 * seek error
	 */
	private static final int PLAYER_ERROR_SEEK = 200;

	/*
	 * mediaPlayerGetStatus return value
	 */
	private static final int PLAYER_STATUS_INIT        = 0;
	private static final int PLAYER_STATUS_PREPARING   = 1;
	private static final int PLAYER_STATUS_PREPARED    = 2;
	private static final int PLAYER_STATUS_PLAYING     = 3;
	private static final int PLAYER_STATUS_PAUSED      = 4;
	private static final int PLAYER_STATUS_SEEKING     = 5;
	private static final int PLAYER_STATUS_REBUFFERING = 6;
	private static final int PLAYER_STATUS_EOS         = 7;
	private static final int PLAYER_STATUS_STOPED      = 8;

	private static final int PLAYER_STATUS_ERROR       = 9;


	AndroidMediaCodec dp;
	
	static playerCommandHandler commandHandler;
	static int video_width, video_height;
	int screen_w, screen_h;
	static int player = -1;
	SurfaceView sv = null;
	protected static ViewGroup mLayout;
	PlayerHelper mPlayerhelper = null;
	
	GestureDetector mGestureDetector = null;
    /** Called when the activity is first created. */
	private int verticalMinDistance = 20;  
	private int minVelocity         = 0; 
	private Boolean hasvideo =false;
	private Boolean surfaceCreated = false;
	private long  pos = 0;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,   
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        mPlayerhelper = new PlayerHelper();
		mPlayerhelper.initPlayerSystem("xxx", this,0);


     //   initPlayerSystem("xxxx");
        player = createMediaPlayer();
        mediaPlayerSetDataSourceUrl(player, SAMPLE);
		mediaPlayerPrepare(player);

        // Handler for the messages
        commandHandler = new playerCommandHandler();
        commandHandler.set_Activity(this);
        mGestureDetector= new GestureDetector(this);
    }
    @Override
    public void onDestroy(){
    	super.onDestroy();
    	sv = null;
		dp = null;
		if (player >=0)
			releaseMediaPlayer(player);
		player = -1;
	    mPlayerhelper.uninitPlayerSystem();
		System.exit(0);
    }
    
   public void creatSurface() {
		sv = new SurfaceView(this);
        FrameLayout.LayoutParams llp = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT);
        mLayout = new FrameLayout(this);
        mLayout.setBackgroundColor(Color.BLACK);
        mLayout.addView(sv);
        sv.setOnTouchListener(this);
        setContentView(mLayout);
        llp.gravity = Gravity.CENTER;
        sv.setLayoutParams(llp);
        dp = new AndroidMediaCodec();
        dp.initJniInterface();
		sv.getHolder().addCallback(this);
   }

    /*
     * Create the player
     * @return the index of the player created
     */

    public native int createMediaPlayer();

    /*
     * Set the uri to mediaplayer
     */
	public native void mediaPlayerSetDataSourceUrl(int  mediaplayer, String url);
	
	/*
	 * stop the mediaplayer
	 */
	public native void stopMediaPlayer(int mediaPlayer);

	/*
	 * release the mediaplayer
	 */
	public native void releaseMediaPlayer(int mediaPlayer);

	/*
	 * set the java surface to mediaplayer ,and the player will render the video to the surface 
	 */
	public native void mediaPlayerSetSurface(int mediaPlayer, Surface surface);

	/*
	 * player will connect the uri and start to deal with the media,
	 * player will notify out if the dealing is done (PLAYER_EVENT_PREPAREDONE)or fail (PLAYER_EVENT_ERROR_NO_STREAM)
	 */
	public native void mediaPlayerPrepare(int mediaPlayer);

	/*
	 *  start to play the media after PLAYER_EVENT_PREPAREDONE
	 */
	public native void mediaPlayerStart(int mediaPlayer);

	/*
	 * pause the player
	 */
	public native void mediaPlayerPause(int mediaPlayer);

	/*
	 * seek to time_us point
	 */
	public native void mediaPlayerSeek(int mediaPlayer, long time_ms);

	/*
	 * Get the player status
	 */
	public native int mediaPlayerGetStatus(int mediaPlayer);

	/*
	 * Get the play position
	 */
	public native long mediaPlayerGetPosition(int mediaPlayer);

	/*
	 * Get the media duration
	 */
	public native long mediaPlayerGetDuration(int mediaPlayer);
	
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		// TODO Auto-generated method stub
		screen_w = width;
		screen_h = height;
		setWindowSize(video_width, video_height);

	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		if (player >=0){
			dp.SetSurface(holder.getSurface());
			mediaPlayerSetSurface(player, holder.getSurface());
		}else {
	        player = createMediaPlayer();
	        mediaPlayerSetDataSourceUrl(player, SAMPLE);
	        long startPos = pos - 2*1000;
	        if (startPos > 0){
	        	Log.d(TAG,"start from " + startPos);
	        	mediaPlayerSeek(player, startPos);
	        }
			mediaPlayerPrepare(player);
		}
		surfaceCreated = true;
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		if (player >= 0){
			pos = mediaPlayerGetPosition(player);
			releaseMediaPlayer(player);
			player = -1;
		}
		surfaceCreated = false;

	}
	
	public void playerEventCallBack(int player_index, int event)
	{
		sendCommand(event, player_index,0,null);
	}
 
	public void videoSzieCallback(int player_index, int w, int h)
	{
		// TODO: if there is more than one player, set the player_index 's  size
		video_width = w;
		video_height = h;
		sendCommand(PLAYER_EVENT_VIDEO_SIZE,player_index,0, null);
	}

	protected class playerCommandHandler extends Handler {
		Context acontext = null;
		@Override
		public void handleMessage(Message msg) {
			int p = msg.arg1;
			switch(msg.what)
			{
			case PLAYER_EVENT_PREPAREDONE:
				if (hasvideo && !surfaceCreated){
					int index = 0;
					while (!surfaceCreated && index < 10){
						index++;
						try {
							Thread.sleep(10);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}else
					mediaPlayerStart(p);
				break;
			case PLAYER_EVENT_VIDEO_SIZE:
				// TODO: if there is more than one player, set the p's size
				hasvideo = true;
				if (!surfaceCreated)
					creatSurface();
				break;
			case PLAYER_EVENT_SEEK_COMPLETELY:
				break;
			case PLAYER_EVENT_EOS:
				Log.e(TAG,"PLAYER_EVENT_EOS");
				stopMediaPlayer(player);
				hasvideo = false;
				/*
				 * You can use this player without create again
				 */
				//mediaPlayerSetDataSourceUrl(player, SAMPLE);
				//mediaPlayerPrepare(player);
				break;
			case PLAYER_EVENT_REBUFFER_START:
				Toast.makeText(acontext, "auto rebuffering",Toast.LENGTH_SHORT).show();
				break;
			case PLAYER_EVENT_REBUFFER_END:
				Toast.makeText(acontext, "rebuffer end",Toast.LENGTH_SHORT).show();
				break;
			case PLAYER_EVENT_ERROR_NO_STREAM:
				Log.e(TAG,"PLAYER_EVENT_ERROR_NO_STREAM");
				releaseMediaPlayer(p);
				if (p == player)
					player = -1;
				break;
			default:
				break;		
			}			
		}
		
		public void set_Activity(Context context){
			acontext = context;
			return;
			
		}
	}
	// Send a message from the SDLMain thread
	static boolean sendCommand(int command, int arg1,int arg2, Object data) {
		Message msg = commandHandler.obtainMessage();
		msg.what = command;
		msg.arg1 = arg1;
		msg.obj = data;
		return commandHandler.sendMessage(msg);
	}

	public void setWindowSize(int w, int h) {
		// TODO Auto-generated method stub
		LayoutParams lp = sv.getLayoutParams();
		double screen_r = (double)screen_w/screen_h;
		double video_r  =(double) w/h;
		Log.d(TAG,"screen_r is " + screen_r);
		Log.d(TAG,"video_r is " + video_r);
		if (screen_r > video_r){
			lp.height = screen_h;
			lp.width  = (int) ((double) screen_h *video_r);
		}else{
			lp.width = screen_w;
			lp.height = (int) ((double)screen_w /video_r);
		}
/*
		if(screen_w < screen_h) {
			lp.width = screen_w;
			lp.height = screen_h * h /w;
		} else {
			lp.width = screen_h / h * w;
			lp.height = screen_h;
		}
*/
		sv.setLayoutParams(lp);
	}
	
	public static String unitFormat(int i) {
        String retStr = null;
        if (i >= 0 && i < 10)
            retStr = "0" + Integer.toString(i);
        else
            retStr = "" + i;
        return retStr;
    }
	@Override
	public boolean onDown(MotionEvent arg0) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onDown");
		return true;
	}
	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onFling");
		int status = mediaPlayerGetStatus(player);
		if (status < PLAYER_STATUS_PREPARED || status >= PLAYER_STATUS_EOS)
			return false;
		long duration = mediaPlayerGetDuration(player);
		if (duration <= 0)
			return false;
		long time = mediaPlayerGetPosition(player);
		Log.i(TAG,"position is" + time);
		int r;
	    
	    if (e1.getX() - e2.getX() > verticalMinDistance && Math.abs(velocityX) > minVelocity) {   
	        time -= 60*1000;
	        if (time < 0)
	        	time = 0;
	        r = 0;
	    } else if (e2.getX() - e1.getX() > verticalMinDistance && Math.abs(velocityX) > minVelocity) {   
	        time += 60*1000;
		    if (time > duration)
		    	time = duration;
		    r =1;
	    }else
	    	return false;
		Log.i(TAG, "sek to " + time);
		mediaPlayerSeek(player,time);
		
	    time /= 1000;
	    int h = (int)time/3600;
	    time -= h*3600;
	    int m = (int)time/60;
	    int s = (int )time - m*60;
	    String a = null;
	    if (r== 0)
	    	a = "<<";
	    else {
			a= ">>";
		}
	    
	    duration/=1000;
	    int h_d = (int)duration/3600;
	    duration -= h_d*3600;
	    int m_d = (int)duration/60;
	    int s_d = (int )duration - m_d*60;
	    Toast.makeText(this, a +" \n"+ unitFormat(h)+":"+unitFormat(m) +":"+ unitFormat(s) +" / " +unitFormat(h_d) +":" +unitFormat(m_d) +":"+ unitFormat(s_d), Toast.LENGTH_SHORT).show();
		return false;
	}
	@Override
	public void onLongPress(MotionEvent arg0) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onLongPress");
		int ret = mediaPlayerGetStatus(player);
		if (ret == PLAYER_STATUS_STOPED){
			mediaPlayerSetDataSourceUrl(player, SAMPLE);
			mediaPlayerPrepare(player);
			Toast.makeText(this, "restart",Toast.LENGTH_SHORT).show();
		
		}else{
			stopMediaPlayer(player);
			Toast.makeText(this, "stop",Toast.LENGTH_SHORT).show();
		}
	}
	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onScroll");

		return true;
	}
	@Override
	public void onShowPress(MotionEvent arg0) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onShowPress");
	}
	@Override
	public boolean onSingleTapUp(MotionEvent arg0) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onSingleTapUp");
		int ret = mediaPlayerGetStatus(player);
		if (ret == PLAYER_STATUS_PLAYING){
			mediaPlayerPause(player);
			Toast.makeText(this, "pause",Toast.LENGTH_SHORT).show();
		}
		else if (ret == PLAYER_STATUS_PAUSED || ret == PLAYER_STATUS_PREPARED){
			mediaPlayerStart(player);
			Toast.makeText(this, "play",Toast.LENGTH_SHORT).show();
		}
			
		return true;
	}
	@Override
	public boolean onTouch(View arg0, MotionEvent event) {
		// TODO Auto-generated method stub
		return mGestureDetector.onTouchEvent(event);
	}
} 